﻿/********************************************************************************
** project   ： #PROJECTNAME#
** date      ： #CREATIONDATE#
** auth      ： #AUTHORNAME#
** desc      ： 
**
** Version   ： #VERSION#
*********************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// Grid：
/// </summary>
public class Grid : MonoBehaviour
{

    private Node[,] grid;
    public Vector2 gridSize;
    public float nodeRadius;
    private float nodeDiameter;
    public LayerMask WhatLayer;
    public int gridCntX, gridCntY;

    public Transform Player;

    public List<Node> path = new List<Node>();
    private Dictionary<Node, List<Node>> nearDict;
    /// <summary>
    /// 开始
    /// </summary>
    void Start()
    {
        nodeDiameter = nodeRadius * 2;
        gridCntX = Mathf.RoundToInt(gridSize.x / nodeDiameter);
        gridCntY = Mathf.RoundToInt(gridSize.y / nodeDiameter);
        grid = new Node[gridCntX, gridCntY];
        CreateGrid();
        CreateNearNode();
    }

    private void CreateNearNode()
    {
        nearDict = new Dictionary<Node, List<Node>>();
        for (int i = 0; i < gridCntX; i++)
        {
            for (int j = 0; j < gridCntY; j++)
            {
                Node node = grid[i,j];
                nearDict.Add(node, GetPrivateNearNode(node));
            }
        }
    }

    private void CreateGrid()
    {
        Vector3 startPoint = transform.position - gridSize.x / 2 * Vector3.right - gridSize.y / 2 * Vector3.forward;
        for (int i = 0; i < gridCntX; i++)
        {
            for (int j = 0; j < gridCntY; j++)
            {
                Vector3 worldPoint = startPoint + Vector3.right * (i * nodeDiameter + nodeRadius) + Vector3.forward * (j * nodeDiameter + nodeRadius);
                bool walkable = !Physics.CheckSphere(worldPoint, nodeRadius, WhatLayer);
                grid[i, j] = new Node(walkable, worldPoint, i, j);
            }
        }
    }

    /// <summary>
    /// 更新
    /// </summary>
    void Update()
    {

    }
    public Node GetFromPostion(Vector3 postion)
    {
        float percentX = (postion.x + gridSize.x / 2) / gridSize.x;
        float percentY = (postion.z + gridSize.y / 2) / gridSize.y;
        percentX = Mathf.Clamp01(percentX);
        percentY = Mathf.Clamp01(percentY);
        int x = Mathf.RoundToInt((gridCntX - 1) * percentX);
        int y = Mathf.RoundToInt((gridCntY - 1) * percentY);
        return grid[x, y];
    }
    public List<Node> GetNearNode(Node node)
    {
        List<Node> list = null;
        nearDict.TryGetValue(node, out list);
        if(list == null)
        {
            list = GetPrivateNearNode(node);
        }
        return list;
    }
    private List<Node> GetPrivateNearNode(Node node)
    {
        List<Node> list = new List<Node>();
        for (int i = -1; i <= 1; i++)
        {
            for (int j = -1; j <=1; j++)
            {
                if (i == 0 && j == 0)
                    continue;
                int tempX = node._gridX + i;
                int tempY = node._gridY + j;
                if(tempX<gridCntX && tempX>=0 && tempY<gridCntY && tempY>=0)
                {
                    list.Add(grid[tempX, tempY]);
                }
            }
        }
        return list;
    }
    void OnDrawGizmos()
    {
        //return;
        Gizmos.DrawWireCube(transform.position, new Vector3(gridSize.x, 1, gridSize.y));
        if (grid == null)
            return;
        Node playerNode = GetFromPostion(Player.position);
        foreach (var item in grid)
        {
            Gizmos.color = item._canWalk ? Color.white : Color.red;
            Gizmos.DrawCube(item._worldPos, Vector3.one * (nodeDiameter - 0.1f));
        }
        if (path != null)
        {
            foreach (var node in path)
            {
                Gizmos.color = Color.black;
                Gizmos.DrawCube(node._worldPos, Vector3.one * (nodeDiameter - 0.1f));
            }
        }
        if(playerNode != null && playerNode._canWalk)
        {
            Gizmos.color = Color.cyan;
            Gizmos.DrawCube(playerNode._worldPos, Vector3.one * (nodeDiameter - 0.1f));
        }
    }
}